//
// Created by ZLY on 2025/5/7.
//
#ifndef GAME_H
#define GAME_H
#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>
#include <SDL3_ttf/SDL_ttf.h>
#include <SDL3_mixer/SDL_mixer.h>
#include <glm/glm.hpp>
#include <iostream>
#include <string>
#include "resource_store.h"
#include <random>
struct Texture;
class Scene;

class Game {
private:
    glm::vec2 screen_size_ = glm::vec2(0); // 屏幕大小
    volatile bool is_running = true; // 游戏是否运行
    Scene *current_scene_ = nullptr; // 场景
    Scene *next_scene_ = nullptr;
    ResourceStore *resource_store_ = nullptr; // 资源管理器
    SDL_Window *window_ = nullptr; // 窗口
    SDL_Renderer *renderer_ = nullptr; // 渲染器
    TTF_TextEngine *ttf_engine_ = nullptr;
    glm::vec2 mouse_position_ = glm::vec2(0);
    SDL_MouseButtonFlags mouse_button_flags_ = 0;
    std::mt19937 gen_ = std::mt19937(std::random_device{}());
    Uint64 FPS = 60; // 帧率
    Uint64 frameDelay = 0; // 帧延迟 ns
    float dt_ = 0.0f; // 帧时间

    int score_ = 0;
    int high_score_ = 0;

    Game() = default;

    Game(const Game &) = delete;

    Game &operator=(const Game &) = delete;

public:
    /**
     *     获取游戏单例
     */
    static Game &GetInstance() {
        static Game instance;
        return instance;
    }

    /**
     * 运行游戏执行主循环
     */
    void run();

    /**
     * 初始化游戏
     * @param title
     * @param width
     * @param height
     */
    void init(const std::string title, int width, int height);

    /**
     * 处理事件
     */
    void handleEvents();

    /**
     * 更新游戏状态
     */
    void update(float dt);

    /**
     * 渲染游戏
     */
    void render();

    /**
     * 销毁资源
     */
    void clean();

    /**
     * 获取屏幕大小
     */
    glm::vec2 getScreenSize() const { return screen_size_; }

    /**
     * 获取当前场景
     */
    Scene *getCurrentScene() const { return current_scene_; }
    ResourceStore *getResourceStore() const { return resource_store_; }
    /**
     *  工具函数
     *
     */
    void drawGrid(const glm::vec2 &top_left, const glm::vec2 &bottom_right, float grad_with, SDL_FColor fcolor);

    void drawBoundry(const glm::vec2 &top_left, const glm::vec2 &bottom_right, float boundry_width, SDL_FColor fcolor);

    void renderTexture(const Texture &texture, const glm::vec2 &pos, const glm::vec2 &size,
                       const glm::vec2 &mask = glm::vec2(1));

    TTF_Text *createTTF_Text(const std::string text, const std::string font_path, int font_size = 16);

    void renderFillCircle(const glm::vec2 &position, const glm::vec2 &size, float alpha);

    void renderHBar(const glm::vec2 &position, const glm::vec2 &size, float percentage, SDL_FColor color);

    float randomFloat(float min, float max) {
        return std::uniform_real_distribution<float>(min, max)(gen_);
    }

    int randomInt(int min, int max) {
        return std::uniform_int_distribution<int>(min, max)(gen_);
    }

    glm::vec2 randomVec2(const glm::vec2 min, const glm::vec2 max) {
        return glm::vec2(randomFloat(min.x, max.x), randomFloat(min.y, max.y));
    }

    glm::ivec2 randomIVec2(const glm::ivec2 min, const glm::ivec2 max) {
        return glm::ivec2(randomInt(min.x, max.x), randomInt(min.y, max.y));
    }

    glm::vec2 getMousePosition() const { return mouse_position_; }
    SDL_MouseButtonFlags getMouseButtonFlags() const { return mouse_button_flags_; }

    void setScore(int score);

    void addScore(int score);

    int getScore() const { return score_; }
    int getHighScore() const { return high_score_; }
    void setHighScore(int high_score) { high_score_ = high_score; }

    void playMusic(const std::string music_path, bool loop = true) {
        Mix_PlayMusic(resource_store_->getMusic(music_path), loop ? -1 : 0);
    }

    void playSound(const std::string sound_path) {
        Mix_PlayChannel(-1, resource_store_->getSound(sound_path), 0);
    }

    void stopMusic() {
        Mix_HaltMusic();
    }

    void stopSound() {
        Mix_HaltChannel(-1);
    }

    void pauseMusic() {
        Mix_PauseMusic();
    }

    void pauseSound() {
        Mix_Pause(-1);
    }

    void resumeMusic() {
        Mix_ResumeMusic();
    }

    void resumeSound() {
        Mix_Resume(-1);
    }

    bool isMouseInRect(const glm::vec2 &top_left, const glm::vec2 &bottom_right);

    void quit() {
        is_running = false;
    }

    void changeScene(Scene *scene);

    void safeChangeScene(Scene *scene);

    std::string loadTextFile(const std::string &path);

    void drawPoint(std::vector<glm::vec2> &points, glm::vec2 render_pos, SDL_FColor color);
    void updateMouse();
};

#endif // GAME_H
